const chokidar = require("chokidar");
const bodyParser = require("body-parser");
const chalk = require("chalk");
const path = require("path");
const Mock = require("mockjs");

const mockDir = path.join(process.cwd(), "mock");

function registerRoutes(app) {
  let mockLastIndex;
  const { mocks } = require("./index.js");
  const mocksForServer = mocks.map((route) => {
    // eslint-disable-next-line no-use-before-define
    return responseFake(route.url, route.type, route.response);
  });
  for (const mock of mocksForServer) {
    app[mock.type](mock.url, mock.response);
    mockLastIndex = app._router.stack.length;
  }
  const mockRoutesLength = Object.keys(mocksForServer).length;
  return {
    mockRoutesLength: mockRoutesLength,
    mockStartIndex: mockLastIndex - mockRoutesLength,
  };
}

function unregisterRoutes() {
  Object.keys(require.cache).forEach((i) => {
    if (i.includes(mockDir)) {
      delete require.cache[require.resolve(i)];
    }
  });
}

// for mock server
const responseFake = (url, type, respond) => {
  return {
    url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
    type: type || "get",
    response(req, res) {
      console.log("request invoke:" + req.path);
      res.json(
        Mock.mock(respond instanceof Function ? respond(req, res) : respond),
      );
    },
  };
};

module.exports = (app) => {
  // 手动设置 CORS 响应头
  app.use((req, res, next) => {
    // 允许所有域名访问
    res.header("Access-Control-Allow-Origin", "*");

    // 允许的请求方法
    res.header(
      "Access-Control-Allow-Methods",
      "GET, POST, PUT, DELETE, OPTIONS",
    );

    // 允许的请求头
    res.header(
      "Access-Control-Allow-Headers",
      "Content-Type, Authorization, X-Requested-With",
    );

    // 对于 OPTIONS 请求进行处理（预检请求）
    if (req.method === "OPTIONS") {
      res.status(200).end();
    } else {
      next();
    }
  });

  // 解析请求体
  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({ extended: true }));

  // 注册 Mock 路由
  const mockRoutes = registerRoutes(app);
  let mockRoutesLength = mockRoutes.mockRoutesLength;
  let mockStartIndex = mockRoutes.mockStartIndex;

  // 热加载 Mock 路由
  chokidar
    .watch(mockDir, {
      ignored: /mock-server/,
      ignoreInitial: true,
    })
    .on("all", (event, path) => {
      if (event === "change" || event === "add") {
        try {
          // 移除原有的 Mock 路由
          app._router.stack.splice(mockStartIndex, mockRoutesLength);

          // 清除路由缓存
          unregisterRoutes();

          // 重新注册 Mock 路由
          const mockRoutes = registerRoutes(app);
          mockRoutesLength = mockRoutes.mockRoutesLength;
          mockStartIndex = mockRoutes.mockStartIndex;

          console.log(
            chalk.magentaBright(
              `\n > Mock Server hot reload success! changed  ${path}`,
            ),
          );
        } catch (error) {
          console.log(chalk.redBright(error));
        }
      }
    });
};
